package com.inetools.gwetons.shared.timer;

import com.google.gwt.core.client.GWT;
import com.inetools.gwetons.client.timer.TimerControllerGinjector;
import com.inetools.gwetons.shared.logging.LogUtilAdapterTemplate;

/**
 * Factory for TimerControllerIntf object. <br />
 * By default, this will instantiate TimerControllerIntf object by TimerControllerGinModule class via 
 * TimerControllerGinjector class per every call to getTimerControllerInstance method. 
 * (To obtain semi-singleton TimerControllerIntf instance, use TimerUniControllerGinModule instead.)
 * Although TimerControllerImpl object instantiated by TimerControllerGinModule as TimerControllerIntf 
 * implementation is targeted only for JavaScript environment, it is possible to, by developing and 
 * injecting other TimerControllerGinjector implementation class, make this instantiate TimerControllerIntf 
 * object runnable on non-JavaScript object. 
 * @author ay
 */
public class TimerControllerFactory extends LogUtilAdapterTemplate implements TimerControllerFactoryIntf {
	
	@Override
	protected String getNameForLogging() {
		return this.getClass().getName();
	}
	
	protected TimerControllerFactory() {
	}

	private TimerControllerGinjector timerControllerGinjector;
		private Object timerControllerGinjectorLock = new Object();
		public TimerControllerGinjector getTimerControllerGinjector() {
			synchronized( timerControllerGinjectorLock) {
				if ( timerControllerGinjector == null) {
					if ( GWT.isClient()) {
						TimerControllerGinjector ginjector = GWT.create( TimerControllerGinjector.class);
						setTimerControllerGinjector( ginjector);
					}
					else {
						throw new UnsupportedOperationException( 
								"Default TimerControllerGinjector object is available only for JavaScript " 
								+ "environment at client side. To use in non-JavaScript environment, inject " 
								+ "custom TimerControllerGinjector instance created for non-JavaScript " 
								+ "environment."
								);
					}
				}
				return timerControllerGinjector;
			} // synchronized
		}
		public void setTimerControllerGinjector(
				TimerControllerGinjector timerControllerGinjector) {
			synchronized( timerControllerGinjectorLock) {
				this.timerControllerGinjector = timerControllerGinjector;
			} // synchronized
		}

	@Override
	public TimerControllerIntf getTimerControllerInstance() {
		TimerControllerIntf timerControllerIntf 
		= getTimerControllerGinjector().getTimerController();
		
		switch( timerControllerIntf.getTargetEnvironment()) {
		case JavaScript:
			if ( !GWT.isClient()) {
				throw new UnsupportedOperationException(
						"TimerControllerIntf instance being obtained via currently set " 
						+ "TimerControllerGinjector object is designed to run only for " 
						+ "JavaScript environment. Please set other TimerControllerGinjector " 
						+ " class object developped for non-JavaScript or both environment."
						);
			}
			break;
		case NonJavaScript:
			if ( GWT.isClient()) {
				throw new UnsupportedOperationException(
						"TimerControllerIntf instance being obtained via currently set " 
						+ "TimerControllerGinjector object is designed to run only for " 
						+ "non-JavaScript environment. Please set other TimerControllerGinjector " 
						+ " class object developped for JavaScript or both environment."
						);
			}
			break;
		case Both:
			break;
		default:
			throw new UnsupportedOperationException(
					timerControllerIntf.getTargetEnvironment().name() + " is unrecognizable " 
					+ "TargetEnvironment item as of when this version of TimerControllerFactory class " 
					+ "was developped. Please report this error."
					);
		} // switch
		
		return timerControllerIntf;
	}
}
